use crate::settings::*;
use log::{self, info};
use log4rs;
use tokio::signal;
// use axum::{Router, routing::get};
use crate::routes;
use anyhow::{Context, Result};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};

pub struct Server {}

impl Server {
    pub fn init(&self) -> Result<()> {
        self.init_log()?;

        APP_SETTINGS.lock().unwrap().load()?;

        Ok(())
    }

    pub async fn serve(&self) -> Result<()> {
        let port = APP_SETTINGS.lock().unwrap().svr_port;

        let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), port);
        println!("{:?}", addr);
        let listener: tokio::net::TcpListener = tokio::net::TcpListener::bind(addr).await?;

        crate::models::model_state::model_state().await?;


        axum::serve(listener, routes::app())
            .with_graceful_shutdown(shutdown_signal())
            .await
            .with_context(|| "server launch error")
    }

    fn init_log(&self) -> Result<()> {
        let ret = log4rs::init_file("log4rs.yaml", Default::default());
        ret.map_err(|e| tokio::io::Error::new(tokio::io::ErrorKind::Other, e.to_string()))?;

        info!("------------------happy day--------------------");

        Ok(())
    }
}

async fn shutdown_signal() {
    let ctrl_c = async {
        signal::ctrl_c()
            .await
            .expect("failed to install Ctrl+C handler");
    };

    #[cfg(unix)]
    let terminate = async {
        signal::unix::signal(signal::unix::SignalKind::terminate())
            .expect("failed to install signal handler")
            .recv()
            .await;
    };

    #[cfg(not(unix))]
    let terminate = std::future::pending::<()>();

    tokio::select! {
        _ = ctrl_c => {println!("ctrl_c exit!")},
        _ = terminate => {
            println!("terminate exit!")
        },
    }
}
